package haust;

import static org.lwjgl.opengl.GL11.*;
import org.newdawn.slick.opengl.Texture;


public class SceneObject
{
	private ModelContainer model;
	private Texture texture;
	private SoundSource sndSrc;

	private Vec3 position = new Vec3();
	private Vec3 velocity = new Vec3();
	private float scale = 1.0f;
	private Vec4 rotation = new Vec4(1,0,0,0);
	private Vec3 lowBounds = new Vec3();
	private Vec3 highBounds = new Vec3();
	
	/**
	 * 
	 * @param mc Model to be rendered
	 */
	public SceneObject( ModelContainer mc )
	{
		model = mc;
	}
	
	/**
	 * 
	 */
	public void flipYZ()
	{
		model.flipYZ();
	}
	
	/**
	 * Binds a texture (if it exists), translates, rotates and scales the model followed by rendering.
	 */
	void render()
	{
		if( texture != null )
		{
			glEnable(GL_TEXTURE_2D);
			texture.bind();
		}
		
		glPushMatrix();
			glTranslatef(position.getX(), position.getY(), position.getZ());
			glRotatef( rotation.getW(), rotation.getX(), rotation.getY(), rotation.getZ() );
			glScalef(scale, scale, scale);
			
			model.render();
		glPopMatrix();
	}
	
	/**
	 * 
	 * @param degrees
	 * @param x
	 * @param y
	 * @param z
	 */
	public void setRotation( float degrees, float x, float y, float z )
	{
		rotation.setX(x);
		rotation.setY(y);
		rotation.setZ(z);
		rotation.setW(degrees);
	}
	
	/**
	 * 
	 * @param tex
	 */
	public void setTexture(Texture tex)
	{
		texture = tex;
	}
	

	/**
	 * 
	 * @return
	 */
	public float getScale() {
		return scale;
	}


	/**
	 * 
	 * @param scale
	 */
	public void setScale(float scale) {
		this.scale = scale;
	}
	
	/**
	 * 
	 * @param x
	 * @param y
	 * @param z
	 */
	public void setPosition( float x, float y, float z)
	{
		position.setX(x);
		position.setY(y);
		position.setZ(z);
		
		if( sndSrc != null )
		{
			sndSrc.setPos(position);
			sndSrc.setVel(velocity);
		}
	}
	

	/**
	 * Calculates min and max values of the modelcoordinates and stores these in the lowBounds and highBounds
	 */
	public void calcBounds()
	{
		lowBounds.setX( 99999);
		lowBounds.setY( 99999);
		lowBounds.setZ( 99999);
		
		highBounds.setX( -99999 );
		highBounds.setY( -99999 );
		highBounds.setZ( -99999 );
		
		for( int i = 0; i < model.coords.size(); i += 3 )
		{
			if( model.coords.get(i) < lowBounds.getX() )lowBounds.setX( model.coords.get(i) );
			if( model.coords.get(i) > highBounds.getX() )highBounds.setX( model.coords.get(i) );
			
			if( model.coords.get(i+1) < lowBounds.getY() )lowBounds.setY( model.coords.get(i+1) );
			if( model.coords.get(i+1) > highBounds.getY() )highBounds.setY( model.coords.get(i+1) );
			
			if( model.coords.get(i+2) < lowBounds.getZ() )lowBounds.setZ( model.coords.get(i+2) );
			if( model.coords.get(i+2) > highBounds.getZ() )highBounds.setZ(model.coords.get(i+2) );
		}
		
		lowBounds.scale( scale );
		highBounds.scale( scale );
	}
	
	
	/**
	 * Checks if point is inside the bounding box (point > lowBounds && point < highBounds)
	 * 
	 * @param point a 3D Point in world coords
	 * @return
	 */
	public boolean isInsideBounds( Vec3 point )
	{
		if( point.getX() < lowBounds.getX() + position.getX() || point.getX() > highBounds.getX() + position.getX() )		
			return false;
		
		if( point.getY() < lowBounds.getY() + position.getY() || point.getY() > highBounds.getY() + position.getY() )		
			return false;
		
		if( point.getZ() < lowBounds.getZ() + position.getZ() || point.getZ() > highBounds.getZ() + position.getZ() )		
			return false;
		
		return true;
	}
}